import { LitElement, css, html, type PropertyValues } from 'lit'
import { customElement, property, query } from 'lit/decorators.js'
import { init } from 'pptx-preview'
import type PPTXPreviewer from 'pptx-preview/dist/previewer';
import pptxgen from "pptxgenjs";

interface Column {
  width: number;
  height: number;
  content?: Item[];
}

interface Item {
  text: string;
  option: pptxgen.TextPropsOptions;
}

/**
 * An example element.
 *
 * @slot - This element has a slot
 * @csspart button - The button
 */
@customElement('my-element')
export class MyElement extends LitElement {
  /**
   * Copy for the read the docs hint.
   */
  @property()
  docsHint = 'Click on the Vite and Lit logos to learn more'

  /**
   * The number of times the button has been clicked.
   */
  @property({ type: Number })
  count = 0

  @query('#pptx-wrapper')
  wrapper?: HTMLDivElement

  pres: pptxgen = new pptxgen();
  slides: pptxgen.Slide[] = [];
  columnsForSlides: Column[][] = [];
  pptxPrviewer?: PPTXPreviewer;

  protected firstUpdated(_changedProperties: PropertyValues): void {

    // 2. Add a Slide
    let slide = this.pres.addSlide();
    this.columnsForSlides = [[]]
    this.slides = [slide];

    // 3. Add one or more objects (Tables, Shapes, Images, Text and Media) to the Slide
    // let textboxText = "Hello World from PptxGenJS!";
    // let textboxOpts = { x: 1, y: 0.5, color: "363636" };
    // slide.addText(textboxText, textboxOpts);
    // slide.addChart(this.pres.ChartType.line, [
    //   {
    //     name: "Actual Sales",
    //     labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
    //     values: [1500, 4600, 5156, 3167, 8510, 8009, 6006, 7855, 12102, 12789, 10123, 15121],
    //   },
    //   {
    //     name: "Projected Sales",
    //     labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
    //     values: [1000, 2600, 3456, 4567, 5010, 6009, 7006, 8855, 9102, 10789, 11123, 12121],
    //   },
    // ], { x: 1, y: 2, w: 8, h: 4 });
    //调用库的init方法生成一个预览器
    const hostWidth = this.offsetWidth;
    const hostHeight = this.offsetHeight;
    this.pptxPrviewer = init(this.wrapper!, {
      width: hostWidth,
      height: hostHeight - 60 // 减去工具栏高度
    })


    // 4. Save the Presentation
    this.renderPpt();

  }

  renderPpt() {
    this.pres.write({
      outputType: "arraybuffer",
    }).then(res => {
      //调用预览器的preview方法
      this.pptxPrviewer!.preview(res as ArrayBuffer)
    })
  }

  render() {
    return html`
      <div id="pptx-wrapper"></div>
      <div class="toolbar">
        <button @click=${()=>this.addParagraph()}>添加段落</button>
        <button @click=${() => this.addTitle()}>添加标题</button>
        <button @click=${this._addTable}>添加表格</button>
        <button @click=${() => this.exportFile()}>导出文件</button>
      </div>
      <div id="table-editor" class="modal">
        <div class="modal-content">
          <h3>表格编辑器</h3>
          <div id="table-preview"></div>
          <div class="modal-actions">
            <button @click=${this._saveTable}>保存表格</button>
            <button @click=${this._closeTableEditor}>取消</button>
          </div>
        </div>
      </div>
    `
  }

  public addParagraph(content: string | null = null, columnIndex: number = 0) {
    // 弹出输入框获取段落内容
    content ??= prompt('请输入段落内容(支持Markdown格式)');
    if (content) {
      // 获取当前预览的幻灯片
      const slide = this.slides[this.pptxPrviewer!.currentIndex];
      var column = this.columnsForSlides[this.pptxPrviewer!.currentIndex][columnIndex];
      if (!column) {
        column = { width: 8, height: 1 ,content: [] };
        this.columnsForSlides[this.pptxPrviewer!.currentIndex][columnIndex] = column;
      }
      // 计算已有段落的总高度
      let yPosition = 1.5; // 默认起始位置
      const existingTexts = this.columnsForSlides[this.pptxPrviewer!.currentIndex][columnIndex]?.content || [];
      if (existingTexts.length > 0) {
        // 获取最后一个文本对象的位置和高度
        const lastText = existingTexts[existingTexts.length - 1];
        yPosition = Number(lastText.option.y ?? 0) + Number(lastText.option.h ?? 1) + 0.5; // 在最后一个段落下方0.5英寸处添加新段落
      }

      // 解析Markdown内容
      const parsedContents = this._parseMarkdown(content);

      // 添加每个解析后的文本块到幻灯片
      for (const content of parsedContents) {
        const baseOptions = {
          x: 1,
          y: yPosition,
          color: "363636",
          fontSize: 12,
          w: 8,
          h: 1
        };
        
        const finalOptions = {
          ...baseOptions,
          ...content.options
        };

        if (column?.content) {
          column.content.push({
            text: content.text,
            option: finalOptions
          });
        }
        
        // 添加文本到幻灯片
        slide.addText(content.text, finalOptions);
        
        // 更新y位置
        //@ts-ignore
        yPosition += 0.5 + (finalOptions.h || 1);
      }
      
      // 重新渲染PPT预览
      this.renderPpt();
    }
  }

  public addTitle(title: string | null = null) {
    var slide = this.slides[this.pptxPrviewer!.currentIndex];
    title ??= prompt('请输入需要设置的标题', '页面标题');
    slide.addText(title!, {
      x: 1,
      y: 0.5,
      color: "363636",
      // align: 'center',
      bold: true,
    });
    this.renderPpt();
  }


  @query('#table-editor')
  tableEditor?: HTMLDivElement;

  @query('#table-preview')
  tablePreview?: HTMLDivElement;

  private _addTable() {
    if (this.tableEditor) {
      this.tableEditor.style.display = 'block';
      this._initTableEditor();
    }
  }

  private _closeTableEditor() {
    if (this.tableEditor) {
      this.tableEditor.style.display = 'none';
    }
  }

  private _initTableEditor() {
    if (this.tablePreview) {
      this.tablePreview.innerHTML = `
        <table border="1" style="width:100%">
          <tr><td contenteditable>行1列1</td><td contenteditable>行1列2</td></tr>
          <tr><td contenteditable>行2列1</td><td contenteditable>行2列2</td></tr>
        </table>
      `;
    }
  }

  private _saveTable() {
    if (this.tablePreview) {
      const table = this.tablePreview.querySelector('table');
      if (table) {
        const slide = this.slides[this.pptxPrviewer!.currentIndex];
        const tableData = this._htmlTableToArray(table);
        slide.addTable(tableData, {
          x: 1,
          y: 1,
          // colW: [3, 3],
          // border: { pt: 1, color: '000000' }
        });
        this._closeTableEditor();
        this.renderPpt();
      }
    }
  }

  private _htmlTableToArray(table: HTMLTableElement): any[][] {
    const rows = table.rows;
    const result: any[][] = [];
    for (let i = 0; i < rows.length; i++) {
      const cells = rows[i].cells;
      const rowData: any[] = [];
      for (let j = 0; j < cells.length; j++) {
        rowData.push(cells[j].innerText);
      }
      result.push(rowData);
    }
    return result;
  }

  public exportFile(fileName: string | null = null) {
    fileName ??= prompt('请输入要导出的文件名(不需要扩展名):', 'presentation');
    if (fileName) {
      this.pres.writeFile({
        fileName: `${fileName}.pptx`,
        compression: true
      });
    }
  }

  private _parseMarkdown(mdText: string): {text: string, options?: pptxgen.TextPropsOptions}[] {
    const lines = mdText.split('\n');
    const result: {text: string, options?: pptxgen.TextPropsOptions}[] = [];
    
    for (const line of lines) {
      if (!line.trim()) continue;
      
      // 解析标题
      if (line.match(/^#\s+/)) {
        const text = line.replace(/^#+\s+/, '');
        result.push({
          text,
          options: {
            bold: true,
            fontSize: 24,
            breakLine: true
          }
        });
      }
      // 解析列表
      else if (line.match(/^\s*[\*\-+]\s+/)) {
        const text = line.replace(/^\s*[\*\-+]\s+/, '');
        result.push({
          text: `• ${text}`,
          options: {
            bullet: true,
            indentLevel: line.match(/^\s+/)?.[0].length || 0,
            breakLine: true
          }
        });
      }
      // 解析粗体
      else if (line.match(/\*\*(.*?)\*\*/)) {
        const text = line.replace(/\*\*(.*?)\*\*/g, '$1');
        result.push({
          text,
          options: {
            bold: true,
            breakLine: true
          }
        });
      }
      // 解析斜体
      else if (line.match(/\*(.*?)\*/)) {
        const text = line.replace(/\*(.*?)\*/g, '$1');
        result.push({
          text,
          options: {
            italic: true,
            breakLine: true
          }
        });
      }
      // 默认段落
      else {
        result.push({
          text: line,
          options: {
            breakLine: true
          }
        });
      }
    }
    
    return result;
  }

  static styles = css`
    :host {
      display: block;
      width: 100%;
      height: 100vh;
      margin: 0;
      padding: 0;
    }

    .logo {
      height: 6em;
      padding: 1.5em;
      will-change: filter;
      transition: filter 300ms;
    }
    .logo:hover {
      filter: drop-shadow(0 0 2em #646cffaa);
    }
    .logo.lit:hover {
      filter: drop-shadow(0 0 2em #325cffaa);
    }

    .toolbar {
      position: fixed;
      bottom: 0;
      left: 0;
      right: 0;
      height: 60px;
      background: #f5f5f5;
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 1rem;
      border-top: 1px solid #ddd;
    }

    .toolbar button {
      padding: 0.5rem 1rem;
      background: #646cff;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }

    .toolbar button:hover {
      background: #535bf2;
    }

    .modal {
      display: none;
      position: fixed;
      z-index: 1;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0,0,0,0.4);
    }

    .modal-content {
      background-color: #fefefe;
      margin: 15% auto;
      padding: 20px;
      border: 1px solid #888;
      width: 80%;
      max-width: 600px;
    }

    .modal-actions {
      display: flex;
      justify-content: flex-end;
      gap: 10px;
      margin-top: 20px;
    }

    #table-preview {
      margin: 20px 0;
      overflow: auto;
    }

    #table-preview table {
      width: 100%;
      border-collapse: collapse;
    }

    #table-preview td {
      padding: 8px;
      border: 1px solid #ddd;
    }

    #table-preview td[contenteditable] {
      min-width: 100px;
      min-height: 30px;
    }

    #pptx-wrapper {
      width: 100%;
      height: calc(100% - 60px);
    }

    .read-the-docs {
      color: #888;
    }

    ::slotted(h1) {
      font-size: 3.2em;
      line-height: 1.1;
    }

    a {
      font-weight: 500;
      color: #646cff;
      text-decoration: inherit;
    }
    a:hover {
      color: #535bf2;
    }

    button {
      border-radius: 8px;
      border: 1px solid transparent;
      padding: 0.6em 1.2em;
      font-size: 1em;
      font-weight: 500;
      font-family: inherit;
      background-color: #1a1a1a;
      cursor: pointer;
      transition: border-color 0.25s;
    }
    button:hover {
      border-color: #646cff;
    }
    button:focus,
    button:focus-visible {
      outline: 4px auto -webkit-focus-ring-color;
    }

    @media (prefers-color-scheme: light) {
      a:hover {
        color: #747bff;
      }
      button {
        background-color: #f9f9f9;
      }
    }
  `
}

declare global {
  interface HTMLElementTagNameMap {
    'my-element': MyElement
  }
}
